#include "TBase.h"
#include "TScale9.h"
#include "TButton.h"
#include "TImage.h"
#include "TTip.h"
#include "TUI.h"
#include "../utils/Utils.h"
#include "../utils/SoundManager.h"


int readAttrInt(xml_node<> * pItem,const char* cAttr){
    
	if(!cAttr)
		return 0;
    
	xml_attribute<> * pNode = pItem->first_attribute(cAttr);
	if(!pNode)
		return 0;
    
	char * v = pNode->value();
	if(v)
		return atoi(v);
	else
		return 0;
}
void readAttrString(xml_node<> * pItem,const char* cAttr, string & ret){
    ret = "";
	if(!cAttr)
		return;
    
    
	xml_attribute<> * pNode = pItem->first_attribute(cAttr);
    
    
	if(!pNode)
		return;
    
    
	char * v = pNode->value();
	if(v)
		ret.append(v);
}

CCSize readContainSize(xml_node<> * pItem,CCNode* parent){
    CCSize ret;
    string strWidth="";
    readAttrString(pItem, "width",strWidth);
    
    string strHeight="";
    readAttrString(pItem, "height",strHeight);
    int width=0,height=0;
    
    if(strWidth.size()!=0)
    {
        if(strWidth.find("%")!=string::npos){
            replaceStr(strWidth, "%", "");
            
            int per=parseInt(strWidth);
            if (parent) {
                width= (parent->getContentSize().width*per)/100;
            }
        }else{
            width=parseInt(strWidth); 
        }
    }else{
        width=-1;
    }
    
    if(strHeight.size()!=0)
    {
        if(strHeight.find("%")!=string::npos){
            replaceStr(strHeight, "%", "");
            
            int per=parseInt(strHeight);
            if (parent) {
                height= (parent->getContentSize().height*per)/100;
            }
        }else{
            
            height=parseInt(strHeight);
        }
        
    }else{
        height=-1;
    }
    
    ret.width=width;
    ret.height=height;
 
    return ret;
    
}


float readAttrFloat(xml_node<> * pItem,const char* cAttr){
    if(!cAttr)
        return 0.0f;
    
	xml_attribute<> * pNode = pItem->first_attribute(cAttr);
	if(!pNode)
		return 0.0f;
    
	char * v = pNode->value();
	if(v)
		return atof(v);
	else
		return 0.0f;
}

/***************************************************
 * TPanelItem
 **************************************************/





void TPanelItem::updateDisplayedOpacity(GLubyte parentOpacity)
{
	_displayedOpacity = _realOpacity * parentOpacity/255.0;
	
    if (_cascadeOpacityEnabled)
    {
        CCObject* pObj;
        CCARRAY_FOREACH(m_pChildren, pObj)
        {
            CCNodeRGBA* item = dynamic_cast<CCNodeRGBA*>(pObj);
            if (item && item->isVisible())
            {
                item->setOpacity(_displayedOpacity);
            }
        }
    }
}
bool TPanelItem::init(){
    if(!CCNodeRGBA::init()){
        return false;
    }
    setCascadeOpacityEnabled(true);
    return true;
}



CCNode* TPanelItem::tipContainer=NULL;
void TPanelItem::initWidthConf(xml_node<> * pItem){
    xml_attribute<> *pNode=NULL;
    
    pNode = pItem->first_attribute("rotation");
	if(pNode){
        setRotation(readAttrInt(pItem, "rotation"));
    }
	pNode = pItem->first_attribute("rotationY");
	if(pNode){
		setRotationY(readAttrInt(pItem, "rotationY"));
	}
	pNode = pItem->first_attribute("rotationX");
	if(pNode){
		setRotationX(readAttrInt(pItem, "rotationX"));
	}
    
    pNode = pItem->first_attribute("scaleX");
	if(pNode){
        setScaleX(readAttrFloat(pItem, "scaleX"));
    }
    
    pNode = pItem->first_attribute("scaleY");
	if(pNode){
        setScaleY(readAttrFloat(pItem, "scaleY"));
    }
    
    
    pNode = pItem->first_attribute("scale");
	if(pNode){
        setScale(readAttrFloat(pItem, "scale"));
    }
    
    pNode = pItem->first_attribute("x");
	if(pNode){
        setX(readAttrInt(pItem, "x"));
    }
    
    pNode = pItem->first_attribute("y");
	if(pNode){
        setY(readAttrInt(pItem, "y"));
    }
    
	pNode = pItem->first_attribute("right");
	if(pNode){
        setRight(readAttrInt(pItem, "right"));
    }
    
    
    pNode = pItem->first_attribute("horizontalCenter");
	if(pNode){
        setHorizontalCenter(readAttrInt(pItem, "horizontalCenter"));
    }
    
    pNode = pItem->first_attribute("verticalCenter");
	if(pNode){
        setVerticalCenter(readAttrInt(pItem, "verticalCenter"));
    }
    
    
    
    pNode = pItem->first_attribute("left");
	if(pNode){
        setLeft(readAttrInt(pItem, "left"));
    }
 
    
    pNode = pItem->first_attribute("top");
	if(pNode){
        setTop(readAttrInt(pItem, "top"));
    }
    
    pNode = pItem->first_attribute("bottom");
	if(pNode){
        setBottom(readAttrInt(pItem, "bottom"));
    }
    
	pNode = pItem->first_attribute("visible");
	if(pNode){
		string vb;
		readAttrString(pItem, "visible", vb);
		if(vb == "0" || vb == "false") {
			setVisible(false);
		}
	}
}

void TPanelItem::setHorizontalCenter(int n){
    if(m_pParent){
        setX(m_pParent->getContentSize().width/2 -getContentSize().width*getScaleX()/2 +n);
    }
    
}

void TPanelItem::setVerticalCenter(int n){
    if(m_pParent){
        setY(m_pParent->getContentSize().height/2-getContentSize().height*getScaleY()/2+n);
    } 
}

void TPanelItem::setLeft(int n){
    setPositionX(n);
}

void TPanelItem::setRight(int n){
    if(m_pParent){ 
        setPositionX(m_pParent->getContentSize().width-getContentSize().width-n);
    }
}

void TPanelItem::setTop(int n){ 
    setPositionY(-n);
}

void TPanelItem::setBottom(int n){
    if(m_pParent){ 
        setPositionY(-m_pParent->getContentSize().height+getContentSize().height+n);
    }
}

void TPanelItem::setX(int x){
    setPositionX(x);
}
void TPanelItem::setY(int y){
    if(m_pParent){ 
        setPositionY(-y);
    }
}



TPanelItem::TPanelItem(){
    m_pTip=NULL;
    m_bDirty=true;
}


void TPanelItem::selected(){
    showTip();
    CSoundManager::sharedSoundManager()->playBtnSound();
}

void TPanelItem::unselected(){
    
}



void TPanelItem::showTip(){
    
    if(m_pTip==NULL){
        return ;
    }
    
    if(m_pTip && m_pTip->getParent()==NULL && tipContainer){
        tipContainer->addChild(m_pTip);
        if(m_pTip->confPath.size()!=0){ 
            m_pTip->loadConf(m_pTip->confPath);
        }
    }
    
    CCSize winSize=CCDirector::sharedDirector()->getWinSize();
    
    CCPoint containerPos=  getPosInScreen(CCPointZero, this);
     
    
    if(containerPos.x+getContentSize().width/2>winSize.width/2){
        m_pTip->setPositionX(containerPos.x+getContentSize().width/2-m_pTip->getContentSize().width -50);
    }else{
        
        m_pTip->setPositionX(containerPos.x+getContentSize().width/2+50);
    }
    m_pTip->setPositionY(containerPos.y+m_pTip->getContentSize().height/2);
    
    
    if(m_pTip->getPositionX()<=0){
        m_pTip->setPositionX(0);
    }
    if(m_pTip->getPositionX()+m_pTip->getContentSize().width>winSize.width){
        m_pTip->setPositionX(winSize.width-m_pTip->getContentSize().width);
    }
    
    if(m_pTip->getPositionY()>winSize.height){
        m_pTip->setPositionY(winSize.height);
    }
    
    if(m_pTip->getPositionY()-m_pTip->getContentSize().height<0){
        m_pTip->setPositionY(m_pTip->getContentSize().height);
    }
}



void TPanelItem::hideTip(){
    if(m_pTip ){
       ((TTip*)m_pTip)->hide();
    }
}

void TPanelItem::updateGame( float dt /*= 0.0*/ )
{
 
}


/***************************************************
 * TPanel
 **************************************************/

CCObject*     TPanel::m_pStaticListener=NULL;
SEL_MenuHandler  TPanel::m_pStaticfnSelector=NULL;


void TPanel::setStaticTarget(CCObject *rec, SEL_MenuHandler selector){
    m_pStaticListener=rec;
    m_pStaticfnSelector=selector;
}


void TPanel::loadConf(){
    if(confPath.size()==0){
        return;
    }
    loadConf(confPath);
}

void TPanel::loadConf(const string& path){
    if(hasLoadConf){
        return;
    }
    

    xml_document<>* doc= TUI::sharedDirector()->getDoc(path);
    
    if(doc==NULL){ 
		string temp= CCFileUtils::sharedFileUtils()->fullPathForFilename(path.c_str());
        const char * fullPath =temp.c_str();
        unsigned long uSize = 0;
        unsigned char * pData = CCFileUtils::sharedFileUtils()->getFileData(fullPath, "rb", &uSize);
        if(!pData)
            return ;
        
        doc=new xml_document<>();
        doc->parse<0>((char *)pData);
        TUI::sharedDirector()->addDoc(path, doc,pData);
    }
    
    xml_node<> * pRoot = doc->first_node();
	if(!pRoot)
		return;
    
    CCSize size=readContainSize(pRoot,getParent());
    if(size.width ==-1){
        size.width=0;
    } 
    if(size.height==-1){ 
        size.height=0;
    }
    setContentSize(size);
    
	xml_node<> * pItem = pRoot->first_node();
	parseConf(pItem);
    hasLoadConf=true;
    onCreateComplete();
    initMask();
}

void TPanel::initWidthConf(xml_node<> * pItem){
    
    if(!pItem) return;
  
    CCSize size=readContainSize(pItem,getParent());
    if(size.width ==-1) size.width=getContentSize().width; 
    if(size.height==-1) size.height=getContentSize().height; 
    setContentSize(size);
    
    parseConf(pItem->first_node());
    
    if(!hasLoadConf){ 
        onCreateComplete();
        initMask();
    }
}
void TPanel::parseConf(xml_node<> * pItem){
    while (pItem) {
        TPanelItem* item=  TUI::sharedDirector()->createUI(pItem);
        if(item){ 
            
            if(item->tType==T_BUTTON_NAME){
                addChildItem(item); 
            }else if(item->tType==T_COUNT_NAME){
                addChildItem(item);
            }else if(item->tType==T_CHECK_NAME){
                addChildItem(item);
            }else if(item->tType==T_RADIO_NAME){
                addChildItem(item);
            }else if(item->tEvent.size()!=0){
                addChildItem(item);
            }else{
                
                addChild(item);
            }
            string id=item->tId;
            if(id.size()>0)  gUIs.insert(pair<string,TPanelItem*>(id, item));
            
            TPanel* panel=dynamic_cast<TPanel*>(item);             
            if(panel && panel->confPath.size()!=0){
                panel->loadConf(panel->confPath.c_str());
            }
            
            item->initWidthConf(pItem);//大小，子容器 
            item->TPanelItem::initWidthConf(pItem);//坐标 缩放
        }
        pItem=pItem->next_sibling();
        
    }
}


TPanelItem* TPanel::getUI(const string& key){
    
    if(gUIs.find(key)==gUIs.end()){
        return NULL;
    }
    return gUIs[key];
}



void TPanel::onExit(){
    
    CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
    CCNode::onExit();
   
    
}

void  TPanel::onCreateComplete(){
    
}

bool TPanel::init(){
    if(!TPanelItem::init()){
        return false;
    }
    return true;
}

void TPanel::registerWithTouchDispatcher()
{ 
    CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, kCCMenuHandlerPriority, true);
}

void TPanel::onEnter(){
    registerWithTouchDispatcher();
    CCNode::onEnter();
    
}


TPanel::TPanel(){
    m_pMoveListener=NULL;
    m_pfnMoveSelector=NULL;
    gTouchItems=new CCArray();
    m_pSelectedItem=NULL;
    scrollParent=NULL;
    m_pListener=NULL;
    m_pfnSelector=NULL;
    hasLoadConf=false;
    hasInitMask=false;
    m_bTouchEnable=true;
}

TPanel::~TPanel(){
    gUIs.clear();
	gTouchItems->removeAllObjects();
    SAFE_DEL(gTouchItems);
}


void TPanel::clearItems(){
    clearSelect();
    gTouchItems->removeAllObjects();
}

void TPanel::addItem(CCNode* item){
    gTouchItems->addObject(item);
}

void TPanel::addChildItem(CCNode* item){
    addItem(item);
    addChild(item);
    
}

int TPanel::getSelectedIndex(){
    if(m_pSelectedItem==NULL){
        return -1;
    } 
    return gTouchItems->indexOfObject(m_pSelectedItem);
}



void TPanel::clearSelect(){
    
    if(m_pSelectedItem){
        onUnSelectItem(m_pSelectedItem);
    }
}


void TPanel::setSelecetItem(CCNode* node){
    if(!node) return;
    if(m_pSelectedItem){
        onUnSelectItem(m_pSelectedItem);
    }
    
        onSelectItem(node);
   
}

void TPanel::setSelecetIndex(int index){
    if(m_pSelectedItem){
        onUnSelectItem(m_pSelectedItem);
    }
    
    if(index==-1){
        index=0;
    }
    
    if(index>=gTouchItems->count()){
        return;
    }
    CCObject* obj=gTouchItems->objectAtIndex(index);
    if(obj){
        onSelectItem((CCNode*)obj);
    }
}

void TPanel::setTarget(CCObject *rec, SEL_MenuHandler selector)
{
    m_pListener = rec;
    m_pfnSelector = selector;
}

bool TPanel::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent){
 
    if(!m_bTouchEnable){
        return false;
    }
  
    if(scrollParent){
        if( !scrollParent->ccTouchBegan(pTouch,pEvent)){
            return false;
        }
    }
    
    touchStartPos.setPoint(pTouch->getLocation().x,pTouch->getLocation().y);
    
    CCNode* parent=this;
    while(parent){
        if(!parent->isVisible() || !parent->isRunning()){
            
            return false;
        }
        parent=parent->getParent(); 
    }
    
    
    if(gTouchItems->count()<=0){
        return false;
    }
    
    
    CCNode* item=(CCNode*) gTouchItems->objectAtIndex(0);
    if(item==NULL || item->getParent()==NULL){
        return false;
    }
    
    CCPoint targetPos=getPosInTarget(pTouch->getLocation(),item->getParent());
    
    
    CCNode* node= getItemByPos(targetPos.x,targetPos.y);
    if(node==NULL){
        
        return false;
    }else{
        
        TButton* button=dynamic_cast<TButton*>(node);
        if(button ){ 
            if(m_pSelectedItem){
                onUnSelectItem(m_pSelectedItem);
            }
            onSelectItem(button);
            
        }
       
        
    }  
    return true;
}

void TPanel::removeItem(CCNode* node){
    gTouchItems->removeObject(node);
}

CCNode* TPanel::getItemByPos(int nX,int nY){ 
    for(int i=gTouchItems->count()-1;i>=0;i--){
    
        CCNode* pNode =  (CCNode*)(gTouchItems->objectAtIndex(i));
        
        
        if(pNode->isVisible()){
            bool isFind=true;
            
            if( nY<pNode->getPositionY()&&
                nY>pNode->getPositionY()-pNode->getContentSize().height){
                
            }else{
                isFind=false;
            }
            
            
            if(pNode->getScaleX()>0){
                if( nX>pNode->getPositionX() &&
                   nX<pNode->getPositionX()+pNode->getContentSize().width
                   ){
                    
                }else{
                    isFind=false;
                }
            }else {
                if(
                   nX>pNode->getPositionX()-pNode->getContentSize().width &&
                   nX<pNode->getPositionX()
                   ){
                    
                }else{
                    isFind=false;
                }
            }
            
            
            
         
            
            if(isFind)
                return pNode;
        }
        
    }
    return NULL;
}

void TPanel::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent)
{
    
    if(scrollParent){
        scrollParent->ccTouchMoved(pTouch,pEvent);
    }
 /*
    touchMovePos.setPoint(pTouch->getLocation().x,pTouch->getLocation().y);
    if(m_pSelectedItem){
        CCNode* item=(CCNode*) gTouchItems->objectAtIndex(0);
        if(item==NULL){
            return ;
        }
        CCPoint targetPos=getPosInTarget(pTouch->getLocation(),item->getParent());
        
        
        CCNode* node= getItemByPos(targetPos.x,targetPos.y);
        if(node==NULL || node!=m_pSelectedItem){
            
            onUnSelectItem(m_pSelectedItem);
            
        }
    }
   */ 
}

void TPanel::ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent)
{
    
    onUnSelectItem(m_pSelectedItem);
    
}
void TPanel::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
    if(scrollParent){
        scrollParent->ccTouchEnded(NULL,pEvent);
    }
    
    if(gTouchItems->count()<=0){
        return ;
    }
    
    CCNode* item=(CCNode*) gTouchItems->objectAtIndex(0);
    if(item==NULL || item->getParent()==NULL){
        return ;
    }
    CCPoint touchEndPos= (pTouch->getLocation());
    
    float distance= (touchEndPos.x-touchStartPos.x)*(touchEndPos.x-touchStartPos.x)+(touchEndPos.y-touchStartPos.y)*(touchEndPos.y-touchStartPos.y);
    
    if(sqrt(distance)<20){
        
        CCPoint targetPos= getPosInTarget(pTouch->getLocation(),item->getParent());
        
        TButton* button=dynamic_cast<TButton*>(m_pSelectedItem);
        
        if(button){
            onUnSelectItem(button);
            
            if(button->getEnable()){ 
                CSoundManager::sharedSoundManager()->playBtnSound();
                if(button->tEvent.size()){
                    procTuiEvent(button->tEvent,button);
                }
                
                if(m_pStaticListener&& m_pStaticfnSelector)
                    (m_pStaticListener->*m_pStaticfnSelector)(button);
                
            }

            
        }else{
            TPanelItem* node= (TPanelItem*) getItemByPos(targetPos.x,targetPos.y);
            if(node!=NULL){
                if(m_pSelectedItem && node != m_pSelectedItem){
                    onUnSelectItem(m_pSelectedItem);
                }
                
                if(node->tEvent.size()!=0){
                    procTuiEvent(node->tEvent,node); 
                }
                
                if(m_pStaticListener&& m_pStaticfnSelector)
                    (m_pStaticListener->*m_pStaticfnSelector)(node);
                onSelectItem(node);
                
            }
           
        }
        
    }
    
}

void TPanel::procTuiEvent(const string& event,TPanelItem* target){
    if(this->getParent()){
        TPanel* item=dynamic_cast<TPanel*>(this->getParent());
        if(item){
            item->procTuiEvent(event,target);
        }
        
    }
}


void TPanel::initMask(){
    if(hasInitMask){
        return;
    }
    
    hasInitMask=true;
    
    
    
    map<string,TPanelItem*>::iterator it= gUIs.begin();
    
    for (; it!=gUIs.end(); it++) {
        TPanelItem* item=  it->second;
        if(item->tMask.size()!=0 && getUI(item->tMask.c_str())){
            if(item->getParent()){
                item->getParent()->removeChild(item,true);
            }
            
            TPanelItem* mask=getUI(item->tMask.c_str());
            if(mask->getParent()){
                mask->getParent()->removeChild(mask,true);
            }
           CCClippingNode* clipper=CCClippingNode::create();
            
            
            clipper->addChild(item);
            clipper->setAnchorPoint(ccp(0.5,0.5));
            clipper->setAlphaThreshold(0.4f );
            clipper->setStencil(mask);
            clipper->setInverted(mask->tMaskType==1);
            addChild(clipper);
        }
    }
     
}

void TPanel::onSelectItem(CCObject* pNode){
    
    TButton* button=dynamic_cast<TButton*>(pNode);
    if(button){
        
        if(button->getEnable()){ 
            button->selected();
        }
        
        m_pSelectedItem=button;
    }else{
        
		m_pSelectedItem=dynamic_cast<CCNode*>(pNode);
		if(m_pListener&& m_pfnSelector)
			(m_pListener->*m_pfnSelector)(m_pSelectedItem);
        
        TPanelItem* tipContainer=dynamic_cast<TPanelItem*>(pNode);
        if(tipContainer){
            tipContainer->selected(); 
        } 
    }
     
}

void TPanel::onUnSelectItem(CCNode* pNode){
    
    TButton* button=dynamic_cast<TButton*>(pNode);
    if(button){
        if(button->getEnable()){
            button->unselected();
        }
    }else{
        
        TPanelItem* tipContainer=dynamic_cast<TPanelItem*>(pNode);
        if(tipContainer){
            tipContainer->unselected();
        }
        
    }
    m_pSelectedItem=NULL;
}

TScrollPanel* TPanel::getScrollPanel(   const char* name){
    return (TScrollPanel*)this->getUI(name);
    
}

TButton* TPanel::getButton(  const char* name){
    return (TButton*)this->getUI(name);
}

TLabel* TPanel::getLabel(const char* name){
    
    return (TLabel*)this->getUI(name);
}
TImage* TPanel::getImage(const char* name){
    
    return (TImage*)this->getUI(name);
}
TPage* TPanel::getPage(const char* name){
    
    return (TPage*)this->getUI(name);
}
TScale9* TPanel::getScale9(const char* name){
    
    return (TScale9*)this->getUI(name);
}
TTab* TPanel::getTab(const char* name){
    
    return (TTab*)this->getUI(name);
}
TPanel* TPanel::getPanel(const char* name){
    
    return (TPanel*)this->getUI(name);
}

TEditBar* TPanel::getEditBar(const char* name){
    
    return (TEditBar*)this->getUI(name);
}

TCheckBox* TPanel::getCheckBox(const char* name){
    
    return (TCheckBox*)this->getUI(name);
}
TRocker* TPanel::getRocker(const char* name){
    
    return (TRocker*)this->getUI(name);
}

TCount* TPanel::getCount(const char* name){
    
    return (TCount*)this->getUI(name);
}

TVBox* TPanel::getVBox(const char* name){
    
    return (TVBox*)this->getUI(name);
}


TBar* TPanel::getBar(const char* name){
    return (TBar*)this->getUI(name);
    
    
}
TInput*  TPanel::getInput(const char* name){
    return (TInput*)this->getUI(name); 
}


TStrokeLabel* TPanel::getStrokeLabel(const char* name){ 
    return (TStrokeLabel*)this->getUI(name); 
}

TRadio* TPanel::getRadio(const char* name){
    return (TRadio*)this->getUI(name);
    
}

TDropdown* TPanel::getDropdown(const char* name){
    
    return (TDropdown*)this->getUI(name);
}
TAccordion* TPanel::getAccordion(const char* name){
    
    return (TAccordion*)this->getUI(name);
}
